home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / mus / play / tracker_4_31.lzh / tracker / Amiga / main.c < prev    next >
C/C++ Source or Header  |  1995-05-11  |  12KB  |  448 lines

  1. /* amiga/main.c 
  2.     vi:ts=3 sw=3:
  3.  */
  4.  
  5. /* plays sound/noisetracker files on Sparc, silicon graphics.
  6.  * Authors  : Liam Corner - zenith@dcs.warwick.ac.uk
  7.  *            Marc Espie - espie@ens.fr
  8.  *            Steve Haehnichen - shaehnic@ucsd.edu
  9.  *            Andrew Leahy - alf@st.nepean.uws.edu.au
  10.  *
  11.  * Usage    : tracker <filename> 
  12.  *  this version plays compressed files as well.
  13.  *    Modified version of the standard main.c
  14.  */
  15.  
  16. /* $Id: main.c,v 1.13 1995/05/11 12:09:16 espie Exp espie $
  17.  * $Log: main.c,v $
  18.  * Revision 1.13  1995/05/11  12:09:16  espie
  19.  * Fixed up minor bugs.
  20.  *
  21.  * Revision 1.12  1995/02/14  16:51:22  espie
  22.  * *** empty log message ***
  23.  *
  24.  * Revision 1.11  1995/02/13  22:05:42  espie
  25.  * Added new speedmode option.
  26.  *
  27.  * Revision 1.10  1995/01/13  13:31:35  espie
  28.  * *** empty log message ***
  29.  *
  30.  * Revision 1.12  1994/06/22  00:24:51  Espie
  31.  * Added wb2cli, workbench support !
  32.  * File requester !
  33.  * Uncentralized event handling using event management functions.
  34.  * Suppressed calls to run_in_fg().
  35.  * Added check for / in song names to display something sensible
  36.  * in the title bar...
  37.  * Corrected minor previous song bug.
  38.  * Suppressed spurious code.
  39.  * Added CUT/ADD keywords.
  40.  * Branching to amiga version from unix version 3.20
  41.  */
  42.      
  43.  
  44. #include <exec/types.h>
  45. #include <exec/memory.h>
  46. #include <proto/dos.h>
  47. #include <proto/exec.h>
  48. #include <dos/dosasl.h>
  49. #include <dos/dosextens.h>
  50. #include <exec/libraries.h>
  51.      
  52. #include "defs.h"
  53.  
  54. extern char *VERSION;
  55.  
  56. #include <signal.h>
  57.  
  58. #include "song.h"
  59. #include "extern.h"
  60.  
  61. #include "tags.h"
  62. #include "prefs.h"
  63. #include "amiga/amiga.h"
  64. #include "amiga/wb2cli.h"
  65.      
  66. ID("$Id: main.c,v 1.13 1995/05/11 12:09:16 espie Exp espie $")
  67.  
  68.  
  69. LOCAL struct MinList temp;
  70.  
  71. LOCAL void print_usage()
  72.    {
  73.    GENERIC handle;
  74.    
  75.    handle = begin_info("Usage");
  76.    info(handle, "Usage: tracker files OPTIONS");
  77.    info(handle, "HELP               Display usage information");
  78.    info(handle, "QUIET              Print no output other than errors");
  79.    info(handle, "PICKY              Do not tolerate any faults (default is to ignore most)");
  80.    info(handle, "TOLERANT           Ignore all faults");
  81.    info(handle, "VERBOSE            Show text representation of song");
  82.    info(handle, "REPEATS count      Number of repeats (0 is forever) (default 1)");
  83.    info(handle, "SPEED speed        Song speed.  Some songs want 60 (default 50)");
  84.    info(handle, "SPEEDMODE old | normal | finefirst | normalfirst");
  85.    info(handle, "NEW/OLD/BOTH       Select default reading type (default is BOTH)");
  86.    info(handle, "TRANSPOSE n        Transpose notes up by n halftones");
  87.    info(handle, "SCROLL             Show notes scrolling by");
  88.    info(handle, "CUT ab1            Play all instruments except number 1 a and b");
  89.    info(handle, "ADD ab1            Play only instruments except number 1 a and b");
  90.    info(handle, "GUI                open GUI directly");
  91.    end_info(handle);
  92.    }
  93.  
  94. /* arg parser for command-line options. */
  95.  
  96. LOCAL char *template = 
  97. "FILES/M,HELP/S,QUIET/S,TOLERANT/S,PICKY/S,NEW/S,OLD/S,BOTH/S,V=VERBOSE/S,\
  98. TRANS=TRANSPOSE/K/N,R=REPEATS/K,SPEED/K/N,START/K,\
  99. CUT/K,ADD/K,SCROLL/S,GUI/S,SPEEDMODE/K";
  100.  
  101. #define OPT_HELP 1
  102. #define OPT_QUIET 2
  103. #define OPT_TOLERANT 3
  104. #define OPT_PICKY 4
  105. #define OPT_NEW 5
  106. #define OPT_OLD 6
  107. #define OPT_BOTH 7
  108. #define OPT_VERBOSE 8
  109. #define OPT_TRANSPOSE 9
  110. #define OPT_REPEATS 10
  111. #define OPT_SPEED 11
  112. #define OPT_START 12
  113. #define OPT_CUT 13
  114. #define OPT_ADD 14
  115. #define OPT_SHOW 15
  116. #define OPT_GUI 16
  117. #define OPT_SPEEDMODE 17
  118.  
  119. LOCAL LONG args[19];
  120.  
  121. LOCAL struct RDArgs *rdargs = 0;
  122.  
  123. LOCAL void free_args()
  124.    {
  125.    if (rdargs)
  126.       FreeArgs(rdargs);
  127.    }
  128.  
  129. /* global variable to catch various types of errors
  130.  * and achieve the desired flow of control
  131.  */
  132. int error;
  133.  
  134. LOCAL struct song *do_read_song(name, type)
  135. char *name;
  136. int type;
  137.    {
  138.    struct song *song;
  139.    struct exfile *file;
  140.  
  141.    file = open_file(name, "r", getenv("MODPATH"));
  142.    if (!file)
  143.       return NULL;
  144.    song = read_song(file, type); 
  145.    close_file(file);
  146.    return song;
  147.    }
  148.  
  149. LOCAL int start;
  150. LOCAL int transpose;
  151.  
  152.  
  153. LOCAL void use_options()
  154.    {
  155.    char *s;
  156.    
  157.    if ((s = args[OPT_CUT]) || (s = args[OPT_ADD]))
  158.       {
  159.       char c;
  160.       ULONG imask = 0;
  161.       
  162.       while (c = *s++)
  163.          {
  164.          if (c >= '1' && c <= '9')
  165.             imask |= 1<< (c-'0');
  166.          else if (c >= 'A' && c <= 'Z')
  167.             imask |= 1 << (c-'A'+10);
  168.          else if (c >= 'a' && c <= 'z')
  169.             imask |= 1 << (c-'a'+10);
  170.          }
  171.       if (args[OPT_CUT])
  172.          set_pref_scalar(PREF_IMASK, imask);
  173.       else
  174.          set_pref_scalar(PREF_IMASK, ~imask);
  175.       }        
  176.    if (args[OPT_OLD])
  177.       set_pref_scalar(PREF_TYPE, OLD);
  178.    if (args[OPT_NEW])
  179.       set_pref_scalar(PREF_TYPE, NEW);
  180.    if (args[OPT_SPEEDMODE])
  181.       {
  182.         if (stricmp(args[OPT_SPEEDMODE], "old") == 0)
  183.             set_pref_scalar(PREF_SPEEDMODE, OLD_SPEEDMODE);
  184.         else if (stricmp(args[OPT_SPEEDMODE], "normal") == 0)
  185.             set_pref_scalar(PREF_SPEEDMODE, NORMAL_SPEEDMODE);
  186.         else if (stricmp(args[OPT_SPEEDMODE], "finefirst") == 0)
  187.             set_pref_scalar(PREF_SPEEDMODE, FINESPEED_ONLY);
  188.         else if (stricmp(args[OPT_SPEEDMODE], "normalfirst") == 0)
  189.             set_pref_scalar(PREF_SPEEDMODE, SPEED_ONLY);
  190.        }
  191.    if (args[OPT_SHOW])
  192.       set_pref_scalar(PREF_SHOW, TRUE);
  193.    if (args[OPT_BOTH])
  194.       set_pref_scalar(PREF_TYPE, BOTH);
  195.    if (args[OPT_REPEATS])
  196.       set_pref_scalar(PREF_REPEATS, *((ULONG *)args[OPT_REPEATS]));
  197.    if (args[OPT_SPEED])
  198.       set_pref_scalar(PREF_SPEED, *((ULONG *)args[OPT_SPEED]));
  199.    if (args[OPT_TRANSPOSE])
  200.       transpose = *((LONG *)args[OPT_TRANSPOSE]);
  201.    if (args[OPT_PICKY])
  202.       set_pref_scalar(PREF_TOLERATE, 0);
  203.    else if (args[OPT_TOLERANT])
  204.       set_pref_scalar(PREF_TOLERATE, 2);
  205.    if (args[OPT_START])
  206.       start = *((ULONG *)args[OPT_START]);
  207.    if (args[OPT_HELP])
  208.       {
  209.       print_usage();
  210.       end_all(0);
  211.       }
  212.    if (args[OPT_VERBOSE])
  213.       set_pref_scalar(PREF_DUMP, TRUE);
  214.    }
  215.  
  216. LOCAL struct song *load_song(name)
  217. char *name;
  218.    {
  219.    struct song *song;
  220.    char *buffer;
  221.    int i, j;
  222.    
  223.    i = strlen(name);
  224.    
  225.    for (j = i; j > 0; j--)
  226.       if (name[j] == '/' || name[j] == ':')
  227.          {
  228.          j++;
  229.          break;
  230.          }
  231.    
  232.    buffer = malloc( i - j + 5);
  233.    if (buffer)
  234.       {
  235.       sprintf(buffer, "%s...", name + j);
  236.       status(buffer);
  237.       }
  238.  
  239.    switch(get_pref_scalar(PREF_TYPE))
  240.       {
  241.    case BOTH:
  242.       song = do_read_song(name, NEW);
  243.       if (song)
  244.          break;
  245.       /* FALLTHRU */
  246.    case OLD:
  247.       song = do_read_song(name, OLD);
  248.       break;
  249.       /* this is explicitly flagged as a new module,
  250.        * so we don't need to look for a signature.
  251.        */
  252.    case NEW:
  253.       song = do_read_song(name, NEW_NO_CHECK);
  254.       break;
  255.       }
  256.    if (buffer)
  257.       {
  258.       status(0);
  259.       free(buffer);
  260.       }
  261.    return song;
  262.    }
  263.  
  264.  
  265. #define PATHSIZE 250
  266.  
  267. struct MinList *expand_names(char *pat[])
  268.    {
  269.    int i;
  270.    struct AnchorPath *ap;
  271.    int error;
  272.    int total;
  273.    struct amiganame *new;
  274.    
  275.    NewList(&temp);
  276.    ap = AllocVec(sizeof(struct AnchorPath) + PATHSIZE, MEMF_CLEAR);
  277.    if (!ap)
  278.       end_all(0);
  279.    ap->ap_Strlen = PATHSIZE;
  280.    for (i = 0; pat && pat[i]; i++)
  281.       {
  282.       for (error = MatchFirst(pat[i], ap); !error; error = MatchNext(ap))
  283.          {
  284.          total = strlen(ap->ap_Buf) +1 ;
  285.          if (strcmp(ap->ap_Buf + total -6, ".info") == 0)
  286.             continue;
  287.          new = malloc(sizeof(struct amiganame) + total);
  288.          if (!new)
  289.             continue;
  290.          strcpy(new->s, ap->ap_Buf);
  291.          new->i = TRUE;
  292.             AddTail(&temp, new);
  293.          }
  294.       MatchEnd(ap);
  295.       }
  296.    FreeVec(ap);
  297.    return &temp;
  298.    }
  299.       
  300. /* add test for >=37 */
  301.  
  302. XT struct DosLibrary *DOSBase;      
  303. XT struct WBStartup *_WBenchMsg;
  304.  
  305. int main(argc, argv)
  306. int argc;
  307. char **argv;
  308.    {
  309.    struct song *song;
  310.    struct MinList *list;
  311.    struct amiganame *element, *i;
  312.  
  313.    struct tag *result;
  314.  
  315.    if (DOSBase->dl_lib.lib_Version < 37)
  316.       end_all("Need OS >= 2.04");
  317.  
  318.    start = 0;
  319.    set_pref_scalar(PREF_IMASK, 0);
  320.    set_pref_scalar(PREF_BCDVOL, 0);
  321.    set_pref_scalar(PREF_DUMP, FALSE);
  322.    set_pref_scalar(PREF_SHOW, FALSE);
  323.    set_pref_scalar(PREF_SYNC, FALSE);
  324.    set_pref_scalar(PREF_TYPE, BOTH);
  325.    set_pref_scalar(PREF_REPEATS, 1);
  326.    set_pref_scalar(PREF_SPEED, 50);
  327.    set_pref_scalar(PREF_TOLERATE, 1);
  328.  
  329.    if (argc == 1)
  330.       {
  331.       print_usage();
  332.       end_all(0);
  333.       }
  334.  
  335.    transpose = read_env("TRANSPOSE", 0);
  336.  
  337.  
  338.    if (argc > 0)     /* CLI */
  339.       {
  340.       /* check the command name for default reading type */
  341.  
  342.       rdargs = ReadArgs(template, args, 0);
  343.       if (rdargs)
  344.          at_end(free_args);
  345.       else
  346.          end_all(0);
  347.    
  348.       use_options();
  349.    
  350.       list = expand_names(args[0]);
  351.       }
  352.    else
  353.       (void)WB2CLI(_WBenchMsg, 4000, DOSBase);
  354.  
  355. again:      
  356.    if (argc == 0 || args[OPT_GUI])
  357.       {
  358.          /* force the interface to appear BEFORE the requester */
  359.       status(0);
  360.       launch_requester();
  361.       list = 0;
  362.       forever
  363.          {
  364.          result = get_ui();
  365.          while (result = get_tag(result))
  366.             {
  367.                /* forgotten from previous versions ! */
  368.             if (result->type == UI_QUIT)
  369.                end_all(0);
  370.             if (result->type == UI_LOAD_SONG)
  371.                {
  372.                i = (struct amiganame *)result->data.pointer;
  373.                if (!i)
  374.                   end_all(0);
  375.                temp.mlh_Tail = 0;
  376.                temp.mlh_Head = i;
  377.                temp.mlh_TailPred = i->n.mln_Pred;
  378.                i->n.mln_Pred->mln_Succ = &(temp.mlh_Tail);
  379.                i->n.mln_Pred = &temp;
  380.                list = &temp;
  381.                break;
  382.                }
  383.             }
  384.          if (list)
  385.             break;
  386.          await_events();
  387.          }
  388.       }
  389.       
  390.    for (element = list->mlh_Head; element->n.mln_Succ; element = element->n.mln_Succ)
  391.       {
  392.       if (!element->i)
  393.          continue;
  394.       song = load_song(element->s);   
  395.       if (song)
  396.          element->i = TRUE;
  397.       else
  398.          {
  399.          char buffer[150];
  400.  
  401.          sprintf(buffer, "%s is not a song", element->s);
  402.          notice(buffer);
  403.          element->i = FALSE;
  404.          continue;
  405.          }
  406. play_on:
  407.       if (get_pref_scalar(PREF_DUMP))
  408.          dump_song(song); 
  409.       transpose_song(song, transpose);
  410.       setup_audio(0, 1, 1);   /* doesn't really matter on the amiga */
  411.       set_busy_pointer(FALSE);
  412.       result = play_song(song, start);
  413.       set_busy_pointer(TRUE);
  414.       release_song(song);
  415.       while (result = get_tag(result))
  416.          {
  417.          switch (result->type)
  418.             {
  419.          case PLAY_PREVIOUS_SONG:
  420.             for (element = element->n.mln_Pred; element->n.mln_Pred; 
  421.                element = element->n.mln_Pred)
  422.                if (element->i)
  423.                   {
  424.                   song = load_song(element->s);
  425.                   goto play_on;
  426.                   }
  427.             break;
  428.          case PLAY_LOAD_SONG:
  429.                /* splice play load song result into list */
  430.             i = (struct amiganame *)result->data.pointer;
  431.             element->n.mln_Succ->mln_Pred = i->n.mln_Pred;
  432.             i->n.mln_Pred->mln_Succ = element->n.mln_Succ;
  433.             element->n.mln_Succ = i;
  434.             i->n.mln_Pred = element;
  435.          default:
  436.             break;
  437.             }
  438.          result++;
  439.          }
  440.             
  441.       }
  442.    if (argc == 0 || args[OPT_GUI])
  443.       goto again;
  444.    end_all(0);
  445.    /* NOTREACHED */
  446.    }
  447.  
  448.